﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Web;
using System.Net;
using System.IO;

class Communications
{
    string UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64; rv:2.0.1) Gecko/20100101 Firefox/4.0.1";

    public ProxyInfo proxyInfo { get; set; }
    public CookieContainer cookieMonster = new CookieContainer();

    public Communications()
    {
        System.Net.ServicePointManager.ServerCertificateValidationCallback += delegate(object sender,
            System.Security.Cryptography.X509Certificates.X509Certificate certificate,
            System.Security.Cryptography.X509Certificates.X509Chain chain,
            System.Net.Security.SslPolicyErrors sslPolicyErrors)
        { return true; };
    }

    public void ClearCookies()
    {
        cookieMonster = new CookieContainer();
    }

    public class ProxyInfo
    {
        public string IP { get; set; }
        public string Port { get; set; }
        public string User { get; set; }
        public string Password { get; set; }

        public override string ToString()
        {
            if (User != null) return string.Join(":", new string[] { IP, Port, User, Password });
            else return string.Join(":", new string[] { IP, Port });
        }
    }

    HttpWebRequest PrepareWebRequest(string url, string referer = "", string accept = "", bool allowAutoRedirect = true)
    {
        var proxyBasicUri = new Uri(url);

        if (proxyInfo != null)
        {
            NetworkCredential nc = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
            CredentialCache cache = new CredentialCache();
            cache.Add(proxyBasicUri, "Basic", nc);
        }

        var request = HttpWebRequest.Create(proxyBasicUri) as HttpWebRequest;
        request.AllowAutoRedirect = allowAutoRedirect;
        request.CookieContainer = cookieMonster;
        request.UserAgent = UserAgent;
        request.Proxy = GetProxy();
        request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8";
        request.Timeout = 60000;
        if (referer != "") request.Referer = referer;
        if (accept != "") request.Accept = accept;

        return request;
    }

    public string PerformGet(string url, string referer = "", string accept = "", bool allowAutoRedirect = false)
    {
        var request = PrepareWebRequest(url, referer, accept, allowAutoRedirect);
        request.Method = "GET";
        return ReadResponseStream(request);
    }

    WebProxy GetProxy()
    {
        if (proxyInfo != null)
        {
            var proxy = new WebProxy(proxyInfo.IP, int.Parse(proxyInfo.Port));
            if (proxyInfo.User != "")
                proxy.Credentials = new NetworkCredential(proxyInfo.User, proxyInfo.Password);
            return proxy;
        }
        return new WebProxy();
    }

    public string PerformPost(string url, PostData postData, string referer = "", bool allowAutoRedirect = false)
    {
        try
        {
            var request = PrepareWebRequest(url, referer, allowAutoRedirect: allowAutoRedirect);
            request.Method = "POST";
            request.ContentType = "application/x-www-form-urlencoded; charset=utf-8";

            byte[] bytes = Encoding.ASCII.GetBytes(postData.ToString());
            request.ContentLength = bytes.Length;

            using (Stream writeStream = request.GetRequestStream())
            {
                writeStream.Write(bytes, 0, bytes.Length);
            }
            return ReadResponseStream(request);
        }
        catch (WebException e)
        {
            if (e.Status == WebExceptionStatus.ProtocolError)
            {
                WebResponse resp = e.Response;
                using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                {
                    var f = sr.ReadToEnd();
                    return f;
                }
            }
        }
        catch (Exception ex)
        {
            return null;
        }
        return null;
    }

    string ReadResponseStream(HttpWebRequest request)
    {
        try
        {
            using (HttpWebResponse response = (HttpWebResponse)request.GetResponse())
            {
                response.Cookies = cookieMonster.GetCookies(request.RequestUri);
                using (Stream responseStream = response.GetResponseStream())
                {
                    using (StreamReader readStream = new StreamReader(responseStream, Encoding.UTF8))
                    {
                        readStream.BaseStream.ReadTimeout = 60000;
                        return readStream.ReadToEnd();
                    }
                }
            }
        }
        catch (WebException e)
        {
            if (e.Status == WebExceptionStatus.ProtocolError)
            {
                WebResponse resp = e.Response;
                using (StreamReader sr = new StreamReader(resp.GetResponseStream()))
                {
                    var f = sr.ReadToEnd();
                    return f;
                }
            }
        }
        catch (Exception ex)
        {
            return null;
        }
        return null;
    }

    public class PostData
    {
        private Dictionary<string, string> Values = new Dictionary<string, string>();

        public void AddValue(string key, string value)
        {
            Values.Add(key, HttpUtility.UrlEncode(value));
        }

        public override string ToString()
        {
            List<string> values = new List<string>();
            foreach (KeyValuePair<string, string> pair in Values)
            {
                values.Add(pair.Key + "=" + pair.Value);
            }
            return string.Join("&", values.ToArray());
        }
    }
}